<template>
  <div class="table">
    <div class="table-header">
      <div class="table-title">{{ title }}</div>
      <div class="toolbar" :style="toolbarStyle">
        <slot name="toolbar"> </slot>
      </div>
    </div>
    <el-table
      id="elTable"
      ref="elTable"
      :data="tableData"
      :border="border"
      :style="{ width: width }"
      :stripe="stripe"
      :fit="fit"
      :size="size"
      :show-header="showHeader"
      :show-summary="showSummary"
      :sum-text="sumText"
      :empty-text="emptyText"
      :header-cell-style="headerCellStyle"
      :row-class-name="rowClassName"
      :highlight-current-row="highlightCurrentRow"
      :tooltip-effect="tooltipEffect"
      @selection-change="handleSelectionChange"
      @sort-change="sortChange"
      @filter-change="filterChange"
      v-loading="loading"
      :max-height="maxHeight"
    >
      <!--  -->
      <!-- 是否显示复选框 -->
      <el-table-column
        type="selection"
        width="40"
        v-if="selection"
        align="center"
      ></el-table-column>
      <el-table-column type="expand" v-if="expand">
        <template slot-scope="scope">
          <slot name="expand" :row="scope.row" :index="scope.$index"></slot>
        </template>
        <slot> </slot>
      </el-table-column>
      <template v-for="(item, index) in column">
        <!-- 序号列 -->
        <el-table-column
          v-if="item.type == 'index'"
          v-bind="{ ...item }"
          :key="index"
        ></el-table-column>
        <!-- 存在插槽的情况 -->
        <el-table-column
          v-else-if="item.isSlot"
          :key="index"
          v-bind="{ ...item }"
        >
          <template
            :slot="item.headerTooltip ? 'header' : 'headerTooltip'"
            slot-scope="scope"
          >
            {{ item.label }}
            <el-tooltip :content="item.headerTooltip" placement="top">
              <i class="el-icon-question"></i>
            </el-tooltip>
          </template>
          <template slot-scope="scope">
            <slot
              :name="item.prop"
              :row="scope.row"
              :index="scope.$index"
            ></slot>
          </template>
        </el-table-column>
        <!-- 普通文本 -->
        <el-table-column v-else v-bind="{ ...item }" :key="index">
          <template
            :slot="item.headerTooltip ? 'header' : 'headerTooltip'"
            slot-scope="scope"
          >
            {{ item.label }}
            <el-tooltip :content="item.headerTooltip" placement="top">
              <i class="el-icon-question"></i>
            </el-tooltip>
          </template>
          <template slot-scope="scope">
            <!-- 存在render函数的情况 -->
            <renderSlot
              v-if="item.render"
              :render="item.render"
              :row="scope.row"
              :index="scope.$index"
              :column="item"
            />
            <span v-else>{{ scope.row[item.prop] || "" }}</span>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <z-pagination
      v-if="!isPagination"
      @handle-page-change="handlePageChange"
      :page-sizes="pageSizeList"
      :layout="layout"
      :prev-text="prevText"
      :next-text="nextText"
      :pagination="pagination"
    />
  </div>
</template>

<script>
import zPagination from "./pagination";
// 自定义内容的组件配置项可以使用render函数进行渲染
// render函数用法
// https://blog.csdn.net/qq_36711388/article/details/88980908
var renderSlot = {
  functional: true,
  props: {
    row: Object,
    render: Function,
    index: Number,
    column: {
      type: Object,
      default: null,
    },
  },
  render: (h, data) => {
    const params = {
      row: data.props.row,
      index: data.props.index,
    };
    if (data.props.column) params.column = data.props.column;
    return data.props.render(h, params);
  },
};
export default {
  name: "ryTable",
  components: {
    zPagination,
    renderSlot,
  },
  props: {
    tooltipEffect: String,
    // 是否显示复选框
    selection: { type: Boolean, default: false },
    // 表格最大高度
    maxHeight: {
      type: String,
      default: "auto",
    },
    //表格标题
    title: { type: String, default: "" },
    // 表格宽度
    width: { type: String, default: "100%" },
    //表格是否需要带表框
    border: { type: Boolean, default: true },
    // 是否为斑马纹 table
    stripe: { type: Boolean, default: false },
    // 列的宽度是否自撑开
    fit: { type: Boolean, default: true },
    // 表格型号：mini,medium,small
    size: { type: String, default: "mini" },
    // 是否显示表头
    showHeader: { type: Boolean, default: true },
    // 是否在表尾显示合计行
    showSummary: { type: Boolean, default: false },
    // 合计行第一列的文本
    sumText: { type: String, default: "合计" },
    // 是否高亮显示当前行
    highlightCurrentRow: { type: Boolean, default: false },
    // 行的 className 的回调方法，也可以使用字符串为所有行设置一个固定的 className
    rowClassName: Function || String,
    // 空数据时显示的文本内容
    emptyText: { type: String, default: "暂无数据" },
    // 表格头部样式
    headerCellStyle: {
      type: Object,
      default: () => {
        return {
          color: "#383838",
          background: "#f5f7fa",
          textAlign: "center",
        };
      },
    },
    // 表格数据
    tableData: { type: Array, default: () => [] },
    // 表头数据
    column: { type: Array, default: () => [] },
    // 加载数据等待状态
    loading: { type: Boolean, default: false },
    //点击页码后是否滚到顶端
    needToTop: { type: Boolean, default: true },
    // 分页组件
    layout: {
      type: String,
      default: "total, sizes, prev, pager, next, jumper",
    },
    // 分页配置
    pagination: {
      type: Object,
      default: () => {},
    },
    // 每页显示的条数
    pageSizeList: {
      type: Array,
      default: () => [5, 10, 15, 20],
    },
    //自定义上一页按钮
    prevText: String,
    //自定义下一页按钮
    nextText: String,
    // 是否开启展开行自定义模板
    expand: Boolean,
    // 按钮组件样式
    toolbarStyle: {
      type: Object,
      default: () => ({
        justifyContent: "flex-end",
      }),
    },
  },
  computed: {
    //分页数据存在才显示分页组件（默认为空对象不显示）
    isPagination: function () {
      return this.isEmpty(this.pagination);
    },
  },
  data() {
    return {};
  },
  methods: {
    //复选框事件，返回选中的数据
    handleSelectionChange(val) {
      this.$emit("selection-change", val);
    },
    //自定义排序
    sortChange(column) {
      this.$emit("sort-change", column);
    },
    // 过滤条件改变
    filterChange(column) {
      this.$emit("filter-change", column);
    },
    handlePageChange(pagination) {
      this.$emit("handle-page-change", pagination);
    },
    // 判断是否为对象
    isObject(x) {
      const type = typeof x;
      return x !== null && (type === "object" || type === "function");
    },
    //判断是否为空对象或空数组
    isEmpty(obj) {
      if (!obj && obj !== 0 && obj !== "") {
        return true;
      }
      if (Array.isArray(obj) && obj.length === 0) {
        return true;
      }
      if (this.isObject(obj) && Object.keys(obj).length === 0) {
        return true;
      }
      return false;
    },
  },
};
</script>

<style lang="scss" scoped>
.table {
  height: 100%;
  margin: auto;
  background: #fff;
  padding: 5px;
  .table-header {
    display: flex;
    align-content: center;
    .table-title {
      display: flex;
      align-items: center;
      font-size: 16px;
    }
    .toolbar {
      margin-right: 20px;
      flex: 1;
      display: flex;
      align-content: center;
      justify-content: flex-end;
    }
  }

  #elTable {
    margin-top: 5px;
  }
}
</style>
